use chrono::prelude::*;
use csv::Writer;
use plotters::prelude::*;
use std::collections::HashSet;
use std::error::Error;
use std::fs;
use std::io::Write;



pub struct TradeRecord {
    pub date: String,             // 日期
    pub symbol: String,           // 品种
    pub trade_type: &'static str, // 交易类型 (buy/sell,buy_short/sell_short)
    pub volume: u32,              // 交易数量
    pub price: f64,               // 交易价格
}
pub struct AccountRecord {
    pub date: String,           // 日期
    pub available_cash: f64,    // 可用资金
    pub market_value: f64,      // 总市值 (持仓市值)
    pub total_assets: f64,      // 总资产
    pub total_profit_loss: f64, // 总盈亏
}
pub struct PositionRecord {
    pub date: String,              // 交易日期
    pub symbol: String,            // 标的代码
    pub long_quantity: u32,        // 多头持仓
    pub long_average_cost: f64,    // 多头成本
    pub long_unrealized_pnl: f64,  // 多头浮盈
    pub long_market_value: f64,    // 多头市值
    pub short_quantity: u32,       // 空头持仓
    pub short_average_cost: f64,   // 空头成本
    pub short_unrealized_pnl: f64, // 空头浮盈
    pub short_market_value: f64,   // 空头市值
}
// 为 TradeRecord 实现 CSV 输出
impl TradeRecord {
    pub fn write_to_csv(records: &[TradeRecord], filename: &str) -> Result<(), Box<dyn Error>> {
        let mut wtr = Writer::from_path(filename)?;

        // 写入表头
        wtr.write_record(&["date", "symbol", "trade_type", "volume", "price"])?;

        // 写入数据
        for record in records {
            wtr.write_record(&[
                &record.date,
                &record.symbol,
                record.trade_type,
                &record.volume.to_string(),
                &record.price.to_string(),
            ])?;
        }

        wtr.flush()?;
        Ok(())
    }
}

// 为 AccountRecord 实现 CSV 输出
impl AccountRecord {
    pub fn write_to_csv(records: &[AccountRecord], filename: &str) -> Result<(), Box<dyn Error>> {
        let mut wtr = Writer::from_path(filename)?;

        wtr.write_record(&[
            "date",
            "available_cash",
            "market_value",
            "total_assets",
            "total_profit_loss",
        ])?;

        for record in records {
            wtr.write_record(&[
                &record.date,
                &record.available_cash.to_string(),
                &record.market_value.to_string(),
                &record.total_assets.to_string(),
                &record.total_profit_loss.to_string(),
            ])?;
        }

        wtr.flush()?;
        Ok(())
    }
}

// 为 PositionRecord 实现 CSV 输出
impl PositionRecord {
    pub fn write_to_csv(records: &[PositionRecord], filename: &str) -> Result<(), Box<dyn Error>> {
        let mut wtr = Writer::from_path(filename)?;

        wtr.write_record(&[
            "date",
            "symbol",
            "long_quantity",
            "long_average_cost",
            "long_unrealized_pnl",
            "long_market_value",
            "short_quantity",
            "short_average_cost",
            "short_unrealized_pnl",
            "short_market_value",
        ])?;

        for record in records {
            wtr.write_record(&[
                &record.date,
                &record.symbol,
                &record.long_quantity.to_string(),
                &record.long_average_cost.to_string(),
                &record.long_unrealized_pnl.to_string(),
                &record.long_market_value.to_string(),
                &record.short_quantity.to_string(),
                &record.short_average_cost.to_string(),
                &record.short_unrealized_pnl.to_string(),
                &record.short_market_value.to_string(),
            ])?;
        }

        wtr.flush()?;
        Ok(())
    }
}
// 指标结构体
pub struct Metrics {
    pub initial_capital: f64,
    pub final_assets: f64,
    pub total_profit_loss: f64,
    pub total_return: f64,
    pub annualized_return: f64,
    pub max_drawdown: f64,
    pub total_trades: usize,
    pub start_date: String,
    pub end_date: String,
    pub trading_days: usize,
}
/// 日志记录对象
pub struct Record {
    pub trade_log: Vec<TradeRecord>,              //交易动作记录
    pub account_log: Vec<AccountRecord>,          //账户信息记录
    pub account_log_each_bar: Vec<AccountRecord>, //每根bar的账户更新
    pub position_log: Vec<PositionRecord>,        //品种的持仓记录
}
// 为 Record 实现方法,一次性输出所有CSV
impl Record {
    pub fn write_all_to_csv(&self, prefix: &str) -> Result<(), Box<dyn Error>> {
        // 创建 report 目录(如果不存在)
        let report_dir = "report";
        fs::create_dir_all(report_dir)?;

        TradeRecord::write_to_csv(
            &self.trade_log,
            &format!("{}/{}_trades.csv", report_dir, prefix),
        )?;
        AccountRecord::write_to_csv(
            &self.account_log,
            &format!("{}/{}_account.csv", report_dir, prefix),
        )?;
        AccountRecord::write_to_csv(
            &self.account_log_each_bar,
            &format!("{}/{}_account_each_bar.csv", report_dir, prefix),
        )?;
        // PositionRecord::write_to_csv(&self.position_log, &format!("{}/{}_positions.csv", report_dir, prefix))?;
        Ok(())
    }
    // 更新生成报告方法
    pub fn generate_html_report(
        &self,
        prefix: &str,
        initial_capital: f64,
    ) -> Result<(), Box<dyn Error>> {
        let report_dir = "report";
        fs::create_dir_all(report_dir)?;

        let metrics = self.calculate_metrics(initial_capital)?;

        // 生成两个独立的图表
        self.generate_equity_chart(prefix)?;
        self.generate_margin_chart(prefix)?;

        let html_content = self.build_html_content(&metrics, prefix)?;

        let file_path = format!("{}/{}_report.html", report_dir, prefix);
        let mut file = fs::File::create(&file_path)?;
        file.write_all(html_content.as_bytes())?;

        println!("HTML报告已生成: {}", file_path);
        Ok(())
    }

    // 计算关键指标
    fn calculate_metrics(&self, initial_capital: f64) -> Result<Metrics, Box<dyn Error>> {
        if self.account_log.is_empty() {
            return Err("账户记录为空".into());
        }

        let first_record = &self.account_log[0];
        let last_record = self.account_log.last().unwrap();

        // 总盈亏
        let total_profit_loss = last_record.total_assets - initial_capital;

        // 总收益率
        let total_return = (last_record.total_assets - initial_capital) / initial_capital * 100.0;

        // 计算年化收益率
        let annualized_return =
            self.calculate_annualized_return(initial_capital, last_record.total_assets)?;

        // 计算最大回撤
        let max_drawdown = self.calculate_max_drawdown(initial_capital)?;

        // 交易统计
        let total_trades = self.trade_log.len();

        // 交易天数（去重后的日期数量）
        let trading_days = self.get_unique_dates().len();

        Ok(Metrics {
            initial_capital,
            final_assets: last_record.total_assets,
            total_profit_loss,
            total_return,
            annualized_return,
            max_drawdown,
            total_trades,
            trading_days, // 新增
            start_date: first_record.date.clone(),
            end_date: last_record.date.clone(),
        })
    }

    // 获取唯一的交易日期
    fn get_unique_dates(&self) -> HashSet<String> {
        self.account_log
            .iter()
            .map(|record| {
                // 假设日期格式是 "2024-01-01 09:00:00",取日期部分
                if record.date.len() >= 10 {
                    record.date[..10].to_string() // 取 "YYYY-MM-DD"
                } else {
                    record.date.clone()
                }
            })
            .collect()
    }

    // 计算年化收益率
    fn calculate_annualized_return(
        &self,
        initial_capital: f64,
        final_assets: f64,
    ) -> Result<f64, Box<dyn Error>> {
        if self.account_log.len() < 2 {
            return Ok(0.0);
        }
        // 简化计算:假设每天都是交易日,一年250个交易日
        let total_return = (final_assets - initial_capital) / initial_capital;
        let trading_days = self.account_log.len() as f64;
        let years = trading_days / 250.0;

        if years > 0.0 {
            let annualized = (1.0 + total_return).powf(1.0 / years) - 1.0;
            Ok(annualized * 100.0)
        } else {
            Ok(0.0)
        }
    }

    // 计算最大回撤
    fn calculate_max_drawdown(&self, initial_capital: f64) -> Result<f64, Box<dyn Error>> {
        let mut max_equity = initial_capital;
        let mut max_drawdown = 0.0;

        for record in &self.account_log {
            if record.total_assets > max_equity {
                max_equity = record.total_assets;
            }

            let drawdown = (max_equity - record.total_assets) / max_equity * 100.0;
            if drawdown > max_drawdown {
                max_drawdown = drawdown;
            }
        }

        Ok(max_drawdown)
    }
    fn get_dates_from_log(&self) -> Result<Vec<DateTime<Utc>>, Box<dyn Error>> {
        let dates: Vec<DateTime<Utc>> = self
            .account_log
            .iter()
            .map(|record| {
                NaiveDateTime::parse_from_str(&record.date, "%Y-%m-%d %H:%M:%S")
                    .unwrap()
                    .and_utc()
            })
            .collect();

        if dates.is_empty() {
            return Err("No data in account log".into());
        }

        Ok(dates)
    }
    // 生成总资产图表
    fn generate_equity_chart(&self, prefix: &str) -> Result<(), Box<dyn Error>> {
        let picture_dir = "report/picture";  // 完整的目录路径
        std::fs::create_dir_all(picture_dir)?;  // 创建 report/picture/ 目录结构
        let file_path = format!("{}/{}_equity_chart.png", picture_dir, prefix);
        // 恢复原来的尺寸 (1200, 400) 或者使用更大的尺寸
        let root = BitMapBackend::new(&file_path, (1200, 600)).into_drawing_area();
        root.fill(&WHITE)?;

        // 使用公共函数获取日期
        let dates = self.get_dates_from_log()?;

        // 转换为万为单位
        let max_assets = self.get_max_assets() / 10000.0;
        let min_assets = self.get_min_assets() / 10000.0;

        // 使用 ChartBuilder 但不设置系列标签区域
        let mut chart = ChartBuilder::on(&root)
            .caption("Equity Curve (Unit: 10K CNY)", ("sans-serif", 20))
            .margin(10)
            .x_label_area_size(40)
            .y_label_area_size(50)
            .build_cartesian_2d(
                dates[0]..dates[dates.len() - 1],
                min_assets * 0.95..max_assets * 1.05,
            )?;

        // 配置网格 - 不设置图例
        chart
            .configure_mesh()
            .x_desc("")
            .y_desc("")
            .x_label_formatter(&|x| x.format("%m/%d").to_string())
            .y_label_formatter(&|y| format!("{:.1}", y))
            .x_labels(10)
            .y_labels(8)
            .draw()?;

        let points: Vec<(DateTime<Utc>, f64)> = self
            .account_log
            .iter()
            .zip(dates.iter())
            .map(|(record, &date)| (date, record.total_assets / 10000.0))
            .collect();

        // 直接绘制系列,不调用 label() 方法
        chart.draw_series(LineSeries::new(
            points,
            ShapeStyle::from(&RED).stroke_width(3),
        ))?;
        
        root.present()?;
        println!("Equity chart generated: {}", file_path);
        Ok(())
    }

    // 生成持仓市值图表
    fn generate_margin_chart(&self, prefix: &str) -> Result<(), Box<dyn Error>> {
        let picture_dir = "report/picture";  // 完整的目录路径
        std::fs::create_dir_all(picture_dir)?;  // 创建 report/picture/ 目录结构
        let file_path = format!("{}/{}_market_value_chart.png", picture_dir, prefix);

        // 恢复原来的尺寸 (1200, 400) 或者使用更大的尺寸
        let root = BitMapBackend::new(&file_path, (1200, 600)).into_drawing_area();
        root.fill(&WHITE)?;

        // 使用公共函数获取日期
        let dates = self.get_dates_from_log()?;

        // 转换为万为单位
        let max_market_value = self
            .account_log
            .iter()
            .map(|record| record.market_value / 10000.0)
            .fold(0.0, f64::max);

        let min_market_value = self
            .account_log
            .iter()
            .map(|record| record.market_value / 10000.0)
            .fold(f64::INFINITY, f64::min);

        let mut chart = ChartBuilder::on(&root)
            .caption("Market Value Curve (Unit: 10K CNY)", ("sans-serif", 20))
            .margin(10)
            .x_label_area_size(40)
            .y_label_area_size(50)
            .build_cartesian_2d(
                dates[0]..dates[dates.len() - 1],
                min_market_value * 0.95..max_market_value * 1.05,
            )?;

        chart
            .configure_mesh()
            .x_desc("")
            .y_desc("")
            .x_label_formatter(&|x| x.format("%m/%d").to_string())
            .y_label_formatter(&|y| format!("{:.1}", y))
            .x_labels(10)
            .y_labels(8)
            .draw()?;

        let points: Vec<(DateTime<Utc>, f64)> = self
            .account_log
            .iter()
            .zip(dates.iter())
            .map(|(record, &date)| (date, record.market_value / 10000.0))
            .collect();
        
        chart.draw_series(LineSeries::new(
            points,
            ShapeStyle::from(&BLUE).stroke_width(3),
        ))?;
        
        root.present()?;
        println!("Market value chart generated: {}", file_path);
        Ok(())
    }

    fn get_max_assets(&self) -> f64 {
        self.account_log
            .iter()
            .map(|record| record.total_assets)
            .fold(0.0, f64::max)
    }

    fn get_min_assets(&self) -> f64 {
        self.account_log
            .iter()
            .map(|record| record.total_assets)
            .fold(f64::MAX, f64::min)
    }

    // 构建HTML内容
    fn build_html_content(
        &self,
        metrics: &Metrics,
        prefix: &str,
    ) -> Result<String, Box<dyn Error>> {
        let html = format!(
            r#"
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>回测报告 - {}</title>
    <style>
        body {{ font-family: Arial, sans-serif; margin: 20px; }}
        .container {{ max-width: 1200px; margin: 0 auto; }}
        .header {{ text-align: center; margin-bottom: 30px; }}
        .metrics {{
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
            gap: 15px;
            margin-bottom: 30px;
        }}
        .metric-card {{
            background: #f5f5f5;
            padding: 15px;
            border-radius: 5px;
            text-align: center;
            border-left: 4px solid #3498db;
        }}
        .metric-label {{ font-size: 14px; color: #666; margin-bottom: 5px; }}
        .metric-value {{ font-size: 18px; font-weight: bold; margin: 5px 0; }}
        .positive {{ color: #e74c3c; }}
        .negative {{ color: #27ae60; }}
        .chart-section {{
            margin: 20px 0;
            background: white;
            padding: 15px;
            border-radius: 5px;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
        }}
        .chart-title {{
            text-align: center;
            margin-bottom: 10px;
            font-size: 16px;
            font-weight: bold;
            color: #2c3e50;
        }}
        img {{
            max-width: 100%;
            height: auto;
            border: 1px solid #ddd;
            border-radius: 3px;
        }}
        .summary {{
            background: #f8f9fa;
            padding: 15px;
            border-radius: 5px;
            margin-top: 20px;
            border-left: 4px solid #e74c3c;
        }}
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1 style="color: #2c3e50; margin-bottom: 10px;">📊 回测报告</h1>
            <p style="color: #7f8c8d;">策略: <strong>{}</strong> | 周期: {} 至 {}</p>
        </div>

        <div class="metrics">
            <div class="metric-card">
                <div class="metric-label">初始资金</div>
                <div class="metric-value">¥{:.2}</div>
            </div>
            <div class="metric-card">
                <div class="metric-label">最终资产</div>
                <div class="metric-value">¥{:.2}</div>
            </div>
            <div class="metric-card">
                <div class="metric-label">总盈亏</div>
                <div class="metric-value {}">¥{:.2}</div>
            </div>
            <div class="metric-card">
                <div class="metric-label">总收益率</div>
                <div class="metric-value {}">{:.2}%</div>
            </div>
            <div class="metric-card">
                <div class="metric-label">年化收益率</div>
                <div class="metric-value {}">{:.2}%</div>
            </div>
            <div class="metric-card">
                <div class="metric-label">最大回撤</div>
                <div class="metric-value">{:.2}%</div>
            </div>
            <div class="metric-card">
                <div class="metric-label">总交易次数</div>
                <div class="metric-value">{}</div>
            </div>
            <div class="metric-card">
                <div class="metric-label">交易天数</div>
                <div class="metric-value">{}</div>
            </div>
        </div>

        <div class="chart-section">
            <div class="chart-title">📈 总资产曲线</div>
            <img src="picture/{}_equity_chart.png" alt="总资产曲线">
        </div>
        
        <div class="chart-section">
            <div class="chart-title">💰 持仓市值曲线</div>
            <img src="picture/{}_market_value_chart.png" alt="持仓市值曲线">
        </div>

        <div class="summary">
            <h3 style="margin-top: 0; color: #e74c3c;">📋 报告说明</h3>
            <p><strong>初始资金:</strong> ¥{:.2} | <strong>最终资产:</strong> ¥{:.2}</p>
            <p><strong>总收益率:</strong> {:.2}% | <strong>年化收益率:</strong> {:.2}%</p>
            <p><strong>最大回撤:</strong> {:.2}% | <strong>交易次数:</strong> {} 次</p>
            <p><strong>交易周期:</strong> {} 至 {} (共 {} 天)</p>
            <p><strong>报告生成时间:</strong> {}</p>
        </div>
    </div>
</body>
</html>
    "#,
            prefix,
            prefix,
            metrics.start_date,
            metrics.end_date,
            metrics.initial_capital,
            metrics.final_assets,
            if metrics.total_profit_loss >= 0.0 {
                "positive"
            } else {
                "negative"
            },
            metrics.total_profit_loss,
            if metrics.total_return >= 0.0 {
                "positive"
            } else {
                "negative"
            },
            metrics.total_return,
            if metrics.annualized_return >= 0.0 {
                "positive"
            } else {
                "negative"
            },
            metrics.annualized_return,
            metrics.max_drawdown,
            metrics.total_trades,
            metrics.trading_days,
            prefix,
            prefix,
            metrics.initial_capital,
            metrics.final_assets,
            metrics.total_return,
            metrics.annualized_return,
            metrics.max_drawdown,
            metrics.total_trades,
            metrics.start_date,
            metrics.end_date,
            metrics.trading_days,
            Local::now().format("%Y-%m-%d %H:%M:%S")
        );

        Ok(html)
    }
    pub fn calculate_batch_metrics(&self, initial_capital: f64) -> Result<Metrics, Box<dyn Error>> {
        // 复用您现有的 calculate_metrics 逻辑
        self.calculate_metrics(initial_capital)
    }
}
